# TO DO 

# - Use temperature residuals for Haldanes in order to account for the influence of plasticity? 
# - Temperature plots for context 
# - Actual stats (mixed effects model, trait ~ collection temp, with experimental replicate as random effect)
# - ARR for % change to directly compare traits 
# - Framework for quantifying the effects of within- and across-population variation in thermal limits to spatial patterns in vulnerability to warming. Comparing predictions based on 1) median, 2) overall CTmax vs. temp regression, 3) population variation in intercepts, 4) population variation in both slope and intercept

Site Characteristics

site_temps = full_data %>% 
  select(site, season, doy, collection_temp, collection_salinity) %>%  
  distinct() %>% 
  filter(doy > 100) 

Copepods were collected by surface tow from sites across the Western Atlantic at several times throughout the year. The sites are shown below. Temperatures at the time of collection were measured using a manual thermometer. Across the entire set of collections, temperature ranged from 12°C to 36°C.

coords = site_data %>%
  select(site, long, lat) %>%
  distinct()

site_map = map_data("world") %>% 
  filter(region %in% c("USA", "Canada")) %>% 
  ggplot() + 
  geom_polygon(aes(x = long, y = lat, group = group),
               fill = "lightgrey") + 
  coord_map(xlim = c(-85,-60),
            ylim = c(25, 48)) + 
  geom_point(data = coords,
             mapping = aes(x = long, y = lat, colour = site),
             size = 3) +
  scale_colour_manual(values = site_cols) + 
  labs(x = "Longitude", 
       y = "Latitude") + 
  theme_matt(base_size = 16)

site_temp_plot = ggplot(site_temps, aes(x = doy, y = collection_temp, colour = site)) + 
  geom_line(linewidth = 2) + 
  geom_point(size = 5) +
  scale_colour_manual(values = site_cols) + 
  labs(y = "Temperature (°C)",
       x = "Day of the Year") +
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(site_map, site_temp_plot, common.legend = T, legend = "bottom")

Exact locations for the sites are provided here.

site_data %>%  
  arrange(lat) %>%  
  select("Site" = site, "Region" = region, "Lat" = lat, "Long" = long) %>% 
  knitr::kable(align = "c")
Site Region Lat Long
Key Largo Florida 25.28391 -80.33014
Manatee River Florida 27.50561 -82.57277
Ft. Hamer Florida 27.52488 -82.43101
Tyler Cove Maryland 38.35083 -76.22902
Ganey’s Wharf Maryland 38.80555 -75.90906
Esker Point Connecticut 41.32081 -72.00166
Sawyer Park Maine 43.90698 -69.87179
St. Thomas de Kent Wharf New Brunswick 46.44761 -64.63692
Ritchie Wharf New Brunswick 47.00481 -65.56291

Nested within each of the three regions (South, Central, and Northern regions) are pairs of low and high salinity sites:

data.frame("Region" = c("South", "Central", "North"),
           "Low Salinity" = c("Ft. Hamer", "Ganey's Wharf", "Ritchie Wharf"),
           "High Salinity" = c("Manatee River", "Tyler Cove", "St. Thomas de Kent Wharf")) %>% 
  knitr::kable(align = "c")
Region Low.Salinity High.Salinity
South Ft. Hamer Manatee River
Central Ganey’s Wharf Tyler Cove
North Ritchie Wharf St. Thomas de Kent Wharf

 

There are fairly well-established divergences between high salinity and low salinity populations of Acartia tonsa. These sets of geographically proximate but isolated populations provide independent comparisons of the effects of seasonality.

season_cols = c("early" = "grey75", 
                "peak" = "grey50", 
                "late" = "grey25")

sal_regions = data.frame(region = rep(c("South", "Central", "North"), each = 2), 
                         site = c("Ft. Hamer", "Manatee River", 
                                  "Ganey's Wharf", "Tyler Cove", 
                                  "Ritchie Wharf", "St. Thomas de Kent Wharf"),
                         salinity = c("low", "high"))

sal_comps = full_data %>% 
  filter(site %in% sal_regions$site) %>% 
  inner_join(sal_regions, by = c("site")) %>% 
  select( region = region.y, site, salinity, season, doy, collection_temp, collection_salinity,
          size, ctmax, warming_tol) %>% 
  mutate(salinity = fct_relevel(salinity, "low", "high"),
         region = fct_relevel(region, "South", "Central", "North"))

sal_comp_temps = sal_comps %>%  
  select(salinity, season, region, collection_temp, collection_salinity) %>% 
  distinct() %>% 
  ggplot(aes(x = salinity, y = collection_temp, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_point(size = 4) + 
  geom_line(linewidth = 1.5) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "Collection Temp. (°C)",
       x = "") + 
  theme_matt_facets(base_size = 14)

sal_comp_sal = sal_comps %>%  
  select(salinity, season, region, collection_temp, collection_salinity) %>% 
  distinct() %>% 
  ggplot(aes(x = salinity, y = collection_salinity, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_point(size = 4) + 
  geom_line(linewidth = 1.5) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "Collection Salinity (psu)",
       x = "Salinity") + 
  theme_matt_facets(base_size = 14)

ggarrange(sal_comp_temps, sal_comp_sal, nrow = 2, common.legend = T, legend = "right")


# sal_comps %>%  
#   select(site, salinity, season, region, collection_temp, collection_salinity) %>% 
#   distinct() %>% 
#   ggplot(aes(x = collection_salinity, y = collection_temp, colour = site)) + 
#   facet_grid(region~.) + 
#   geom_point(size = 4) + 
#   #stat_ellipse() +
#   #geom_path(arrow = arrow(length = unit(0.1, "inches"), type = "closed")) + 
#   scale_colour_manual(values = site_cols) + 
#   theme_matt_facets(base_size = 14)

Critical Thermal Limits

A total of 376 individuals were examined. Critical thermal limits and body size measurements were made before individuals were preserved in ethanol. We excluded data for 6 individuals, detailed below. These individuals had either very low CTmax or were, upon re-examination of photographs, identified as juveniles instead of mature females.

excluded %>% 
  select(region, site, season, collection_temp, collection_salinity, replicate, tube, ctmax, size) %>% 
  knitr::kable(align = "c")
region site season collection_temp collection_salinity replicate tube ctmax size
Florida Manatee River peak 34.0 29 2 6 38.45833 0.616
Florida Manatee River peak 34.0 29 2 7 38.23750 0.593
Maryland Tyler Cove peak 29.5 15 2 2 36.84375 0.614
Connecticut Esker Point early 22.5 30 2 3 30.02604 0.687
Maine Sawyer Park peak 22.0 30 1 4 30.81424 0.865
New Brunswick St. Thomas de Kent Wharf late 13.5 28 1 3 28.78299 1.039

Critical thermal maxima (CTmax) was measured using a custom setup. The method uses a standard dynamic ramping assay to determine the maximum temperature individuals could sustain normal functioning. This differs from lethal temperatures, and indeed, all individuals observed so far recovered following the assay.

Individuals were rested for one hour after collection before the assay. During the assay, copepods were held in 0.2 um filtered seawater, adjusted to match the salinity at the time of collection with bottled spring water. During the assay, several ‘control’ individuals were maintained in this adjusted salinity solution, but did not experience the temperature ramp, to ensure that there was no background mortality.

Shown below are the measured CTmax values. Note: CTmax values for the early season Key Largo copepods were collected at the end of February 2023 as part of a separate project. Body size values were not measured during this project, nor were copepods individually preserved after the experiments. These early season CTmax values are included as a point of comparison. Individual measurements are shown in small points for each collection. The large point indicates the median value.

mean_ctmax = full_data %>% 
  group_by(site, season, doy, collection_temp) %>% 
  summarize(mean_ctmax = mean(ctmax),
            median_ctmax = median(ctmax))

ggplot(full_data, aes(x = season, y = ctmax, colour = site)) + 
  geom_line(data = mean_ctmax, 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = mean_ctmax, 
             aes(y = median_ctmax),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

ggplot(filter(full_data, site != "Key Largo"), aes(x = doy, y = ctmax, colour = site)) + 
  geom_line(data = filter(mean_ctmax, site != "Key Largo"), 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = filter(mean_ctmax, site != "Key Largo"), 
             aes(y = median_ctmax),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

ggplot(full_data, aes(x = season, y = ctmax, colour = site)) + 
  facet_wrap(.~site, scales = "free_y") + 
  geom_line(data = mean_ctmax, 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 3, alpha = 0.5) + 
  geom_line(data = mean_ctmax, 
            aes(y = collection_temp, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 2,
            colour = "grey") + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.8) + 
  # geom_point(data = mean_ctmax, 
  #            aes(y = median_ctmax),
  #            position = position_dodge(width = 0.4),
  #            size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "none", 
        legend.title.align = 0.125)

ggplot(full_data, aes(x = doy, y = ctmax, colour = site)) + 
  facet_wrap(.~site, scales = "free") + 
  geom_line(data = mean_ctmax, 
            aes(y = median_ctmax, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 3, alpha = 0.5) + 
  geom_line(data = mean_ctmax, 
            aes(y = collection_temp, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 2,
            colour = "grey") + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.8) + 
  # geom_point(data = mean_ctmax, 
  #            aes(y = median_ctmax),
  #            position = position_dodge(width = 0.4),
  #            size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "none", 
        legend.title.align = 0.125)

Warming tolerance

Warming tolerance was calculated as the difference between measured CTmax values and the collection temperature. Lower warming tolerance values indicate that populations were nearer to their upper thermal limits, and may therefore be more vulnerable to additional warming.

mean_wt = full_data %>% 
  group_by(site, season) %>% 
  summarize(mean_wt = mean(warming_tol),
            median_wt = median(warming_tol))

ggplot(full_data, aes(x = season, y = warming_tol, colour = site)) + 
  geom_line(data = mean_wt, 
            aes(y = median_wt, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = mean_wt, 
             aes(y = median_wt),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Warming Tolerance (°C)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

Body Size

Following the CTmax assay, individuals were photographed for body size measurements. Prosome lengths were measured from these photographs using a scale micrometer and the software ImageJ. These measurements are shown below.

mean_size = full_data %>% 
  group_by(site, season, doy, collection_temp) %>% 
  summarize(mean_size = mean(size),
            median_size = median(size))

ggplot(full_data, aes(x = season, y = size, colour = site)) + 
  geom_line(data = mean_size, 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = mean_size, 
             aes(y = median_size),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

ggplot(drop_na(full_data, size), aes(x = doy, y = size, colour = site)) + 
  geom_line(data = drop_na(mean_size, mean_size), 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 1) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.3) + 
  geom_point(data = drop_na(mean_size, mean_size), 
             aes(y = median_size),
             position = position_dodge(width = 0.4),
             size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

ggplot(full_data, aes(x = season, y = size, colour = site)) + 
  facet_wrap(.~site) + 
  geom_line(data = mean_size, 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 3, alpha = 0.5) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.8) + 
  # geom_point(data = mean_ctmax, 
  #            aes(y = median_ctmax),
  #            position = position_dodge(width = 0.4),
  #            size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "none", 
        legend.title.align = 0.125)

ggplot(drop_na(full_data, size), aes(x = doy, y = size, colour = site)) + 
  facet_wrap(.~site) + 
  geom_line(data = drop_na(mean_size, mean_size), 
            aes(y = median_size, group = site),
            position = position_dodge(width = 0.4),
            linewidth = 3, alpha = 0.5) + 
  geom_point(position = position_jitterdodge(jitter.width = 0.1, jitter.height = 0,
                                             dodge.width = 0.4),
             alpha = 0.8) + 
  # geom_point(data = mean_ctmax, 
  #            aes(y = median_ctmax),
  #            position = position_dodge(width = 0.4),
  #            size = 4) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "none", 
        legend.title.align = 0.125)

Salinity Pair Comparisons

sal_comp_ctmax_plot = sal_comps %>% 
  ggplot(aes(x = salinity, y = ctmax, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_point(size = 2,
             position = position_dodge(width = 0.2)) + 
  #geom_line(size = 1.5) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "CTmax (°C)",
       x = "") + 
  theme_matt_facets(base_size = 14)

sal_comp_size_plot = sal_comps %>% 
  ggplot(aes(x = salinity, y = size, colour = season, group = season)) + 
  facet_wrap(region~.) + 
  geom_point(size = 2, 
             position = position_dodge(width = 0.2)) + 
  #geom_line(size = 1.5) + 
  scale_colour_manual(values = season_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "") + 
  theme_matt_facets(base_size = 14)

ggarrange(sal_comp_ctmax_plot, sal_comp_size_plot, nrow = 2, common.legend = T, legend = "right")


###

sal_comp_ctmax.model = lm(ctmax ~ collection_temp, data = sal_comps)
# summary(ctmax_temp.model)
# car::Anova(ctmax_temp.model)
sal_comp_ctmax_resids = residuals(sal_comp_ctmax.model)

sal_comp_size.model = lm(size ~ collection_temp, data = sal_comps)
# summary(size_temp.model)
# car::Anova(size_temp.model)
sal_comp_size_resids = residuals(sal_comp_size.model)

sal_comp_ctmax_resid_plot = sal_comps %>%
  mutate(ctmax_resids = sal_comp_ctmax_resids,
         size_resids = sal_comp_size_resids) %>%
  ggplot(aes(x = salinity, y = ctmax_resids, colour = season, group = season)) +
  facet_wrap(region~.) +
  geom_point(size = 2,
             position = position_dodge(width = 0.5)) +
  #geom_line(size = 1.5) +
  scale_colour_manual(values = season_cols) +
  labs(y = "CTmax \nResiduals",
       x = "") +
  theme_matt_facets(base_size = 14)

sal_comp_size_resid_plot = sal_comps %>%
  mutate(ctmax_resids = sal_comp_ctmax_resids,
         size_resids = sal_comp_size_resids) %>%
  ggplot(aes(x = salinity, y = size_resids, colour = season, group = season)) +
  facet_wrap(region~.) +
  geom_point(size = 2,
             position = position_dodge(width = 0.5)) +
  #geom_line(size = 1.5) +
  scale_colour_manual(values = season_cols) +
  labs(y = "Prosome Length \nResiduals",
       x = "") +
  theme_matt_facets(base_size = 14)

#ggarrange(sal_comp_ctmax_resid_plot, sal_comp_size_resid_plot, nrow = 2, common.legend = T, legend = "right")

Trait Correlations

We expect that collections from warmer waters should yield copepods with higher thermal limits and smaller body sizes.

ctmax_temp_plot = ggplot(full_data, aes(x = collection_temp, y = ctmax)) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2, 
              colour = "grey") + 
  geom_point(aes(colour = site), 
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "none")

size_temp_plot = ggplot(full_data, aes(x = collection_temp, y = size)) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2, 
              colour = "grey") + 
  geom_point(aes(colour = site), 
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Prosome Length (mm)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

wt_temp_plot = ggplot(full_data, aes(x = collection_temp, y = warming_tol)) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2, 
              colour = "grey") + 
  geom_point(aes(colour = site), 
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Warming Tolerance (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(ctmax_temp_plot, wt_temp_plot, size_temp_plot, common.legend = T, legend = "bottom", nrow = 1)

Of particular interest is the relationship between prosome length and CTmax. In many cases, larger body sizes are associated with cold adaptation/acclimation. We may therefore see this pattern emerge across populations or seasons. If populations contain a mix of cold- and warm-adapted genotypes, however, we might also see this relationship emerge within individual collections. Shown below is the relationship between prosome length and CTmax for the individuals measured thus far. Individual regression lines for each site are also included. Note that raw CTmax and body size values are shown, rather than metrics like residuals from a statistical model correcting for variation in collection temperature.

universal_size = full_data %>% 
  ggplot(aes(x = size, y = ctmax)) + 
  # geom_smooth(data = filter(full_data, ctmax > 31), 
  #             aes(x = size, y = ctmax),
  #             method = "lm", 
  #             colour = "grey60", 
  #             se = F,
  #             linewidth = 2) + 
  geom_smooth(method = "lm", se = T,
              linewidth = 2,
              colour = "grey70") + 
  geom_point(aes(colour = site),
             size = 2, alpha = 0.7) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax (°C)",
       x = "") +
  theme_matt(base_size = 14) + 
  theme(legend.position = "right",
        axis.title.x = element_blank())

pop_size = full_data %>% 
  ggplot(aes(x = size, y = ctmax, colour = site, group = season)) + 
  facet_wrap(site~.) + 
  # geom_smooth(data = filter(full_data, ctmax > 31), 
  #             aes(x = size, y = ctmax),
  #             method = "lm", 
  #             colour = "grey60", 
  #             se = F,
  #             linewidth = 2) + 
  geom_point(size = 1.3, alpha = 0.3) + 
  geom_smooth(data = full_data, 
              aes(x = size, y = ctmax, group = site), 
              colour = "grey70", method = "lm", se = F) + 
  geom_smooth(method = "lm", se = F,
              linewidth = 1) + 
  scale_colour_manual(values = site_cols) + 
  scale_x_continuous(breaks = c(0.6, 0.8, 1)) + 
  labs(y = "CTmax (°C)",
       x = "Prosome Length (mm)") +
  theme_matt(base_size = 14) + 
  theme(legend.position = "right")

ggarrange(universal_size, pop_size, common.legend = T, legend = "none", nrow = 2)

Trait Variability

Shown below is the trait variation (ranges) for each site. Ranges are calculated for each season separately.

trait_ranges = full_data %>% 
  group_by(site, season, collection_temp, collection_salinity, doy, lat) %>% 
  summarise(mean_ctmax = mean(ctmax),
            ctmax_range = max(ctmax) - min(ctmax),
            ctmax_var = var(ctmax),
            mean_size = mean(size),
            size_range = max(size) - min(size),
            size_var = var(size)) %>% 
  mutate(prop_ctmax_range = ctmax_range / mean_ctmax,
         prop_size_range = size_range / mean_size)

ctmax_range_temp = ggplot(trait_ranges, aes(x = collection_temp, y = ctmax_range, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Range (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

ctmax_var_temp = ggplot(trait_ranges, aes(x = collection_temp, y = ctmax_var, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Range (°C)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

size_range_temp = ggplot(trait_ranges, aes(x = collection_temp, y = size_range, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Size Range (mm)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

size_var_temp = ggplot(trait_ranges, aes(x = collection_temp, y = size_var, colour = site)) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "Size Range (mm)",
       x = "Collection Temp. (°C)") +
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(ctmax_range_temp, size_range_temp, common.legend = T, legend = "bottom")

Changes in trait variance may be indicative of phenotypic selection. If selection (as opposed to acclimation) are driving seasonal changes, we may expect to see a reduction in variance in the peak samples relative to the early season samples. Note that early season collection temperatures this year were higher than expected, driven by fairly strong heatwaves in the North Atlantic.

ggplot(trait_ranges, aes(x = season, y = ctmax_var, colour = site)) + 
  geom_line(aes(group = site), 
            linewidth = 1.5) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(y = "CTmax Variance",
       x = "Season") +
  theme_matt() + 
  theme(legend.position = "right", 
        legend.title.align = 0.125)

Comparing rates of change (Haldanes)

Both CTmax and body size varied between sites and across seasons. It can be difficult to directly compare these two traits. We take two approaches to ease this comparison. Shown below is a comparison of the slopes from the trait regressions against collection temperature for each population, standardized by the standard deviation of the trait for each population (across all collections). This presents change per degree change in collection temperature in units of standard deviations for both CTmax and body size.

adj_slopes = full_data %>% 
  group_by(site, lat) %>% 
  arrange(doy) %>%  
  filter(site != "Key Largo") %>%
  summarize("ctmax_slope" = coef(lm(ctmax ~ collection_temp))["collection_temp"], 
            "mean_ctmax" = mean(ctmax),
            "ctmax_sd" = sd(ctmax),
            "size_slope" = coef(lm(size ~ collection_temp))["collection_temp"], 
            "mean_size" = mean(size),
            "size_sd" = sd(size), 
            "temp_range" = max(collection_temp) - min(collection_temp)) %>%  
  drop_na() %>% 
  mutate(adj_ctmax_slope = ctmax_slope / ctmax_sd,
         adj_size_slope = size_slope / size_sd) %>% 
  pivot_longer(cols = starts_with("adj_"), 
               names_to = "slope_type",
               names_prefix = "adj_",
               values_to = "slope")

# ggplot(adj_slopes, aes(x = lat, y = temp_range)) + 
#   geom_point() + 
#   theme_matt()

ggplot(adj_slopes, aes(x = slope_type, y = abs(slope), 
                       group = site, colour = site)) + 
  geom_hline(yintercept = 0) + 
  geom_line(linewidth = 1) + 
  scale_colour_manual(values = site_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Haldanes are a similar unit, representing change in units of standard deviations per generation. This can be a useful metric for comparing across traits, especially as the number of generations covered by our sampling period likely varies across populations. The calculation of haldanes is taken from Hendry and Kinnison (1999), which in turn is based on work from Gingerich (1993). We estimated the number of generations passed between collections using the empirical relationship between temperature and development time from ____. For initial estimates, we used a temperature halfway in between collections.

early_peak = full_data %>% 
  filter(season %in% c("early", "peak")) %>% 
  mutate(season = if_else(season == "early", "one", "two")) %>% 
  group_by(site) %>% 
  mutate(ctmax_sd_p = sd(ctmax),
         size_sd_p = sd(size), 
         temp_change = max(collection_temp) - min(collection_temp),
         avg_temp = (max(collection_temp) + min(collection_temp)) / 2,
         days_passed = max(doy) - min(doy)) %>% 
  select(site, lat, season, 
         ctmax_sd_p, size_sd_p, 
         temp_change, avg_temp, days_passed, 
         ctmax, size) %>%
  group_by(site, lat, season, 
           ctmax_sd_p, size_sd_p, 
           temp_change, avg_temp, days_passed) %>% 
  summarize(ctmax = mean(ctmax),
            size = mean(size)) %>% 
  pivot_wider(id_cols = c(site, lat, ctmax_sd_p, size_sd_p, 
                          temp_change, avg_temp, days_passed), 
              names_from = season, 
              values_from = c(ctmax, size)) %>% 
  mutate(season = "early_to_peak") %>%  
  drop_na()

peak_late = full_data %>% 
  filter(season %in% c("peak", "late")) %>% 
  mutate(season = if_else(season == "peak", "one", "two")) %>% 
  group_by(site) %>% 
  mutate(ctmax_sd_p = sd(ctmax),
         size_sd_p = sd(size), 
         temp_change = last(collection_temp) - first(collection_temp),
         avg_temp = (max(collection_temp) + min(collection_temp)) / 2,
         days_passed = max(doy) - min(doy)) %>% 
  select(site, lat, season, ctmax_sd_p, size_sd_p, 
         temp_change, avg_temp, days_passed, 
         ctmax, size) %>%
  group_by(site, lat, season, ctmax_sd_p, size_sd_p, 
           temp_change, avg_temp, days_passed) %>% 
  summarize(ctmax = mean(ctmax),
            size = mean(size)) %>% 
  pivot_wider(id_cols = c(site, lat, ctmax_sd_p, size_sd_p, 
                          temp_change, avg_temp, days_passed), 
              names_from = season, 
              values_from = c(ctmax, size)) %>% 
  mutate(season = "peak_to_late") %>%  
  drop_na()

calc_halds = function(x1, x2, sd_p, g){
  ((x2 / sd_p) - (x1 / sd_p)) / g
}

haldanes = bind_rows(early_peak, peak_late) %>% 
  mutate("gen_time" = 5490*(avg_temp + 1)^-2.05, 
         "gens" = floor(days_passed / gen_time),
         "ctmax_haldanes" = calc_halds(x2 = ctmax_two, x1 = ctmax_one, 
                                       sd_p = ctmax_sd_p, g = gens),
         "size_haldanes" = calc_halds(x2 = size_two, x1 = size_one, 
                                      sd_p = size_sd_p, g = gens))

haldanes %>% 
  ungroup() %>% 
  select(site, season, ctmax_haldanes, size_haldanes) %>% 
  pivot_longer(cols = c(ctmax_haldanes, size_haldanes),
               names_to = c("type", NA), 
               names_sep = "_",
               values_to = "haldanes") %>% 
  ggplot(aes(x = type, y = haldanes, group = site, colour = site)) + 
  facet_wrap(season~.) + 
  geom_hline(yintercept = 0) + 
  geom_line(linewidth = 1) + 
  scale_colour_manual(values = site_cols) + 
  theme_matt_facets()

Shown below are the haldane values plotted against latitude.

ctmax_haldanes = ggplot(haldanes, aes(x = lat, y = ctmax_haldanes, colour = site, shape = season)) + 
  geom_hline(yintercept = 0) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Latitude",
       y = "Change in CTmax (haldanes)") + 
  theme_matt_facets()

size_haldanes = ggplot(haldanes, aes(x = lat, y = size_haldanes, colour = site, shape = season)) + 
  geom_hline(yintercept = 0) + 
  geom_point(size = 3) + 
  scale_colour_manual(values = site_cols) + 
  labs(x = "Latitude",
       y = "Change in Size (haldanes)") + 
  theme_matt_facets()

ggarrange(ctmax_haldanes, size_haldanes, common.legend = T, legend = "right", nrow = 2)

Next Steps

After phenotyping, each individual was preserved in 95% ethanol. Individual DNA libraries will be prepared using Twist Bio 96-plex prep kits, then sequenced on an Illumina NovaSeq X Plus. Using the low-coverage whole genome sequences, we will examine seasonal patterns in allele frequency change, and compare these fine scale temporal patterns with the larger latitudinal patterns in allele frequency to determine whether the same alleles driving rapid seasonal adaptation are in play over larger spatial (and longer temporal) scales.

Misc. Details

ggplot(temp_record, aes(x = minute_passed, y = temp_C, group = factor(run))) + 
  geom_abline(slope = 0.3, intercept = mean(temp_record[temp_record$minute_interval == 0, 8])) + 
  geom_abline(slope = 0.1, intercept = mean(temp_record[temp_record$minute_interval == 0, 8])) + 
  geom_line(linewidth = 0.2, alpha = 0.8) + 
  geom_point(data = full_data, 
             aes(x = time, y = ctmax + 0.4),
             size = 2,
             shape = 25) +
  labs(x = "Time passed (minutes)",
       y = "Temperature (degrees C)",
       fill = "Trial Number") + 
  guides(colour = "none") + 
  theme_matt(base_size = 16) + 
  theme(legend.position = "right")

ramp_record2 = ramp_record %>% 
  group_by(run, minute_interval) %>% 
  summarise(mean_ramp = mean(ramp_per_minute)) %>% 
  ungroup()

ggplot(ramp_record2, aes(x = minute_interval, y = mean_ramp)) + 
  geom_hline(yintercept = 0.3) + 
  geom_hline(yintercept = 0.1) + 
  #geom_point() + 
  geom_hex(bins = 30) + 
  ylim(0, 0.35) + 
  labs(y = "Ramp Rate (deg. C / min.)",
       x = "Time into run (minute)") + 
  theme_matt(base_size = 16) 

LS0tCnRpdGxlOiAiQ29tcGFyaW5nIHNlYXNvbmFsIGFuZCBsYXRpdHVkaW5hbCBwYXR0ZXJucyBpbiB0aGVybWFsIGFkYXB0YXRpb24iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3J9CiMgVE8gRE8gCgojIC0gVXNlIHRlbXBlcmF0dXJlIHJlc2lkdWFscyBmb3IgSGFsZGFuZXMgaW4gb3JkZXIgdG8gYWNjb3VudCBmb3IgdGhlIGluZmx1ZW5jZSBvZiBwbGFzdGljaXR5PyAKIyAtIFRlbXBlcmF0dXJlIHBsb3RzIGZvciBjb250ZXh0IAojIC0gQWN0dWFsIHN0YXRzIChtaXhlZCBlZmZlY3RzIG1vZGVsLCB0cmFpdCB+IGNvbGxlY3Rpb24gdGVtcCwgd2l0aCBleHBlcmltZW50YWwgcmVwbGljYXRlIGFzIHJhbmRvbSBlZmZlY3QpCiMgLSBBUlIgZm9yICUgY2hhbmdlIHRvIGRpcmVjdGx5IGNvbXBhcmUgdHJhaXRzIAojIC0gRnJhbWV3b3JrIGZvciBxdWFudGlmeWluZyB0aGUgZWZmZWN0cyBvZiB3aXRoaW4tIGFuZCBhY3Jvc3MtcG9wdWxhdGlvbiB2YXJpYXRpb24gaW4gdGhlcm1hbCBsaW1pdHMgdG8gc3BhdGlhbCBwYXR0ZXJucyBpbiB2dWxuZXJhYmlsaXR5IHRvIHdhcm1pbmcuIENvbXBhcmluZyBwcmVkaWN0aW9ucyBiYXNlZCBvbiAxKSBtZWRpYW4sIDIpIG92ZXJhbGwgQ1RtYXggdnMuIHRlbXAgcmVncmVzc2lvbiwgMykgcG9wdWxhdGlvbiB2YXJpYXRpb24gaW4gaW50ZXJjZXB0cywgNCkgcG9wdWxhdGlvbiB2YXJpYXRpb24gaW4gYm90aCBzbG9wZSBhbmQgaW50ZXJjZXB0CmBgYAoKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1ULCBtZXNzYWdlID0gRiwgd2FybmluZyA9IEYsIGVjaG8gPSBGfQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBrbml0cjo6aXNfaHRtbF9vdXRwdXQoKSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucGF0aCA9ICIuLi9GaWd1cmVzL21hcmtkb3duLyIsCiAgZGV2ID0gYygicG5nIiwgInBkZiIpLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgY29sbGFwc2UgPSBUCikKCnRoZW1lX21hdHQgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgdGhlbWVfcHVicihiYXNlX2ZhbWlseT0ic2FucyIpICUrcmVwbGFjZSUgCiAgICB0aGVtZSgKICAgICAgcGFuZWwuYmFja2dyb3VuZCAgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gbWlkX3RleHQsIGxpbmVoZWlnaHQgPSAxLjEpLAogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS41LAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBkYXJrX3RleHQpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IG1pZF90ZXh0KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMywgMCwgMCwgMCksICJtbSIpKSwKICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwgNSwgMCwgMCksICJtbSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ2xlID0gOTApLAogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPWJhc2Vfc2l6ZSAqIDAuOSksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMC45LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLjI1LCAwLjI1LCAwLjI1LCAwLjI1LCJjbSIpCiAgICApCn0KCnRoZW1lX21hdHRfZmFjZXRzID0gZnVuY3Rpb24oYmFzZV9zaXplID0gMTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGFya190ZXh0ID0gImdyZXkyMCIpewogIG1pZF90ZXh0IDwtICBtb25vY2hyb21lUjo6Z2VuZXJhdGVfcGFsZXR0ZShkYXJrX3RleHQsICJnb19saWdodGVyIiwgbl9jb2xvdXJzID0gNSlbMl0KICBsaWdodF90ZXh0IDwtICBtb25vY2hyb21lUjo6Z2VuZXJhdGVfcGFsZXR0ZShkYXJrX3RleHQsICJnb19saWdodGVyIiwgbl9jb2xvdXJzID0gNSlbM10KICAKICB0aGVtZV9idyhiYXNlX2ZhbWlseT0ic2FucyIpICUrcmVwbGFjZSUgCiAgICB0aGVtZSgKICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuYmFja2dyb3VuZCAgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gbWlkX3RleHQsIGxpbmVoZWlnaHQgPSAxLjEpLAogICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSksCiAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGRhcmtfdGV4dCksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gbWlkX3RleHQpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygzLCAwLCAwLCAwKSwgIm1tIikpLAogICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLCA1LCAwLCAwKSwgIm1tIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5nbGUgPSA5MCksCiAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9YmFzZV9zaXplICogMC45KSwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAwLjksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJib2xkIiksCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAuMjUsIDAuMjUsIDAuMjUsIDAuMjUsImNtIikKICAgICkKfQoKc2l0ZV9jb2xzID0gYygiS2V5IExhcmdvIiA9ICJpbmRpYW5yZWQ0IiwgCiAgICAgICAgICAgICAgIk1hbmF0ZWUgUml2ZXIiID0gImNvcmFsIiwgCiAgICAgICAgICAgICAgIkZ0LiBIYW1lciIgPSAiY29yYWwzIiwKICAgICAgICAgICAgICAiVHlsZXIgQ292ZSIgPSAiZ29sZGVucm9kMSIsCiAgICAgICAgICAgICAgIkdhbmV5J3MgV2hhcmYiID0gImRhcmtnb2xkZW5yb2QzIiwgCiAgICAgICAgICAgICAgIkVza2VyIFBvaW50IiA9ICJkYXJrc2VhZ3JlZW4zIiwKICAgICAgICAgICAgICAiU2F3eWVyIFBhcmsiID0gInBhbGVncmVlbjQiLCAKICAgICAgICAgICAgICAiU3QuIFRob21hcyBkZSBLZW50IFdoYXJmIiA9ICJzdGVlbGJsdWUyIiwKICAgICAgICAgICAgICAiUml0Y2hpZSBXaGFyZiIgPSAic3RlZWxibHVlNCIpCmBgYAoKIyMgU2l0ZSBDaGFyYWN0ZXJpc3RpY3MKCmBgYHtyfQpzaXRlX3RlbXBzID0gZnVsbF9kYXRhICU+JSAKICBzZWxlY3Qoc2l0ZSwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCwgY29sbGVjdGlvbl9zYWxpbml0eSkgJT4lICAKICBkaXN0aW5jdCgpICU+JSAKICBmaWx0ZXIoZG95ID4gMTAwKSAKYGBgCgpDb3BlcG9kcyB3ZXJlIGNvbGxlY3RlZCBieSBzdXJmYWNlIHRvdyBmcm9tIHNpdGVzIGFjcm9zcyB0aGUgV2VzdGVybiBBdGxhbnRpYyBhdCBzZXZlcmFsIHRpbWVzIHRocm91Z2hvdXQgdGhlIHllYXIuIFRoZSBzaXRlcyBhcmUgc2hvd24gYmVsb3cuIFRlbXBlcmF0dXJlcyBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uIHdlcmUgbWVhc3VyZWQgdXNpbmcgYSBtYW51YWwgdGhlcm1vbWV0ZXIuIEFjcm9zcyB0aGUgZW50aXJlIHNldCBvZiBjb2xsZWN0aW9ucywgdGVtcGVyYXR1cmUgcmFuZ2VkIGZyb20gYHIgbWluKHNpdGVfdGVtcHMkY29sbGVjdGlvbl90ZW1wKWDCsEMgdG8gYHIgbWF4KHNpdGVfdGVtcHMkY29sbGVjdGlvbl90ZW1wKWDCsEMuCgpgYGB7ciBzaXRlLWNoYXJzLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nn0KY29vcmRzID0gc2l0ZV9kYXRhICU+JQogIHNlbGVjdChzaXRlLCBsb25nLCBsYXQpICU+JQogIGRpc3RpbmN0KCkKCnNpdGVfbWFwID0gbWFwX2RhdGEoIndvcmxkIikgJT4lIAogIGZpbHRlcihyZWdpb24gJWluJSBjKCJVU0EiLCAiQ2FuYWRhIikpICU+JSAKICBnZ3Bsb3QoKSArIAogIGdlb21fcG9seWdvbihhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLAogICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Z3JleSIpICsgCiAgY29vcmRfbWFwKHhsaW0gPSBjKC04NSwtNjApLAogICAgICAgICAgICB5bGltID0gYygyNSwgNDgpKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGNvb3JkcywKICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGNvbG91ciA9IHNpdGUpLAogICAgICAgICAgICAgc2l6ZSA9IDMpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTG9uZ2l0dWRlIiwgCiAgICAgICB5ID0gIkxhdGl0dWRlIikgKyAKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE2KQoKc2l0ZV90ZW1wX3Bsb3QgPSBnZ3Bsb3Qoc2l0ZV90ZW1wcywgYWVzKHggPSBkb3ksIHkgPSBjb2xsZWN0aW9uX3RlbXAsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAyKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDUpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgICAgeCA9ICJEYXkgb2YgdGhlIFllYXIiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShzaXRlX21hcCwgc2l0ZV90ZW1wX3Bsb3QsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpFeGFjdCBsb2NhdGlvbnMgZm9yIHRoZSBzaXRlcyBhcmUgcHJvdmlkZWQgaGVyZS4gCgpgYGB7ciBzaXRlLXRhYmxlfQpzaXRlX2RhdGEgJT4lICAKICBhcnJhbmdlKGxhdCkgJT4lICAKICBzZWxlY3QoIlNpdGUiID0gc2l0ZSwgIlJlZ2lvbiIgPSByZWdpb24sICJMYXQiID0gbGF0LCAiTG9uZyIgPSBsb25nKSAlPiUgCiAga25pdHI6OmthYmxlKGFsaWduID0gImMiKQpgYGAKCk5lc3RlZCB3aXRoaW4gZWFjaCBvZiB0aGUgdGhyZWUgcmVnaW9ucyAoU291dGgsIENlbnRyYWwsIGFuZCBOb3J0aGVybiByZWdpb25zKSBhcmUgcGFpcnMgb2YgbG93IGFuZCBoaWdoIHNhbGluaXR5IHNpdGVzOiAgICAKCmBgYHtyIHNhbC10YWJsZX0KZGF0YS5mcmFtZSgiUmVnaW9uIiA9IGMoIlNvdXRoIiwgIkNlbnRyYWwiLCAiTm9ydGgiKSwKICAgICAgICAgICAiTG93IFNhbGluaXR5IiA9IGMoIkZ0LiBIYW1lciIsICJHYW5leSdzIFdoYXJmIiwgIlJpdGNoaWUgV2hhcmYiKSwKICAgICAgICAgICAiSGlnaCBTYWxpbml0eSIgPSBjKCJNYW5hdGVlIFJpdmVyIiwgIlR5bGVyIENvdmUiLCAiU3QuIFRob21hcyBkZSBLZW50IFdoYXJmIikpICU+JSAKICBrbml0cjo6a2FibGUoYWxpZ24gPSAiYyIpCmBgYAoKXCAKClRoZXJlIGFyZSBmYWlybHkgd2VsbC1lc3RhYmxpc2hlZCBkaXZlcmdlbmNlcyBiZXR3ZWVuIGhpZ2ggc2FsaW5pdHkgYW5kIGxvdyBzYWxpbml0eSBwb3B1bGF0aW9ucyBvZiAqQWNhcnRpYSB0b25zYSouIFRoZXNlIHNldHMgb2YgZ2VvZ3JhcGhpY2FsbHkgcHJveGltYXRlIGJ1dCBpc29sYXRlZCBwb3B1bGF0aW9ucyBwcm92aWRlIGluZGVwZW5kZW50IGNvbXBhcmlzb25zIG9mIHRoZSBlZmZlY3RzIG9mIHNlYXNvbmFsaXR5LgoKYGBge3Igc2Vhc29uLXNhbC1jb21wcywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9OH0Kc2Vhc29uX2NvbHMgPSBjKCJlYXJseSIgPSAiZ3JleTc1IiwgCiAgICAgICAgICAgICAgICAicGVhayIgPSAiZ3JleTUwIiwgCiAgICAgICAgICAgICAgICAibGF0ZSIgPSAiZ3JleTI1IikKCnNhbF9yZWdpb25zID0gZGF0YS5mcmFtZShyZWdpb24gPSByZXAoYygiU291dGgiLCAiQ2VudHJhbCIsICJOb3J0aCIpLCBlYWNoID0gMiksIAogICAgICAgICAgICAgICAgICAgICAgICAgc2l0ZSA9IGMoIkZ0LiBIYW1lciIsICJNYW5hdGVlIFJpdmVyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR2FuZXkncyBXaGFyZiIsICJUeWxlciBDb3ZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUml0Y2hpZSBXaGFyZiIsICJTdC4gVGhvbWFzIGRlIEtlbnQgV2hhcmYiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIHNhbGluaXR5ID0gYygibG93IiwgImhpZ2giKSkKCnNhbF9jb21wcyA9IGZ1bGxfZGF0YSAlPiUgCiAgZmlsdGVyKHNpdGUgJWluJSBzYWxfcmVnaW9ucyRzaXRlKSAlPiUgCiAgaW5uZXJfam9pbihzYWxfcmVnaW9ucywgYnkgPSBjKCJzaXRlIikpICU+JSAKICBzZWxlY3QoIHJlZ2lvbiA9IHJlZ2lvbi55LCBzaXRlLCBzYWxpbml0eSwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCwgY29sbGVjdGlvbl9zYWxpbml0eSwKICAgICAgICAgIHNpemUsIGN0bWF4LCB3YXJtaW5nX3RvbCkgJT4lIAogIG11dGF0ZShzYWxpbml0eSA9IGZjdF9yZWxldmVsKHNhbGluaXR5LCAibG93IiwgImhpZ2giKSwKICAgICAgICAgcmVnaW9uID0gZmN0X3JlbGV2ZWwocmVnaW9uLCAiU291dGgiLCAiQ2VudHJhbCIsICJOb3J0aCIpKQoKc2FsX2NvbXBfdGVtcHMgPSBzYWxfY29tcHMgJT4lICAKICBzZWxlY3Qoc2FsaW5pdHksIHNlYXNvbiwgcmVnaW9uLCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHkpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzYWxpbml0eSwgeSA9IGNvbGxlY3Rpb25fdGVtcCwgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsgCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKyAKICBnZW9tX3BvaW50KHNpemUgPSA0KSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjUpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzZWFzb25fY29scykgKyAKICBsYWJzKHkgPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIsCiAgICAgICB4ID0gIiIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCgpzYWxfY29tcF9zYWwgPSBzYWxfY29tcHMgJT4lICAKICBzZWxlY3Qoc2FsaW5pdHksIHNlYXNvbiwgcmVnaW9uLCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHkpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzYWxpbml0eSwgeSA9IGNvbGxlY3Rpb25fc2FsaW5pdHksIGNvbG91ciA9IHNlYXNvbiwgZ3JvdXAgPSBzZWFzb24pKSArIAogIGZhY2V0X3dyYXAocmVnaW9ufi4pICsgCiAgZ2VvbV9wb2ludChzaXplID0gNCkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMS41KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2Vhc29uX2NvbHMpICsgCiAgbGFicyh5ID0gIkNvbGxlY3Rpb24gU2FsaW5pdHkgKHBzdSkiLAogICAgICAgeCA9ICJTYWxpbml0eSIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCgpnZ2FycmFuZ2Uoc2FsX2NvbXBfdGVtcHMsIHNhbF9jb21wX3NhbCwgbnJvdyA9IDIsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAicmlnaHQiKQoKIyBzYWxfY29tcHMgJT4lICAKIyAgIHNlbGVjdChzaXRlLCBzYWxpbml0eSwgc2Vhc29uLCByZWdpb24sIGNvbGxlY3Rpb25fdGVtcCwgY29sbGVjdGlvbl9zYWxpbml0eSkgJT4lIAojICAgZGlzdGluY3QoKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHggPSBjb2xsZWN0aW9uX3NhbGluaXR5LCB5ID0gY29sbGVjdGlvbl90ZW1wLCBjb2xvdXIgPSBzaXRlKSkgKyAKIyAgIGZhY2V0X2dyaWQocmVnaW9ufi4pICsgCiMgICBnZW9tX3BvaW50KHNpemUgPSA0KSArIAojICAgI3N0YXRfZWxsaXBzZSgpICsKIyAgICNnZW9tX3BhdGgoYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDAuMSwgImluY2hlcyIpLCB0eXBlID0gImNsb3NlZCIpKSArIAojICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiMgICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKYGBgCgojIyBDcml0aWNhbCBUaGVybWFsIExpbWl0cwoKQSB0b3RhbCBvZiBgciBkaW0oYWxsX2RhdGEpWzFdYCBpbmRpdmlkdWFscyB3ZXJlIGV4YW1pbmVkLiBDcml0aWNhbCB0aGVybWFsIGxpbWl0cyBhbmQgYm9keSBzaXplIG1lYXN1cmVtZW50cyB3ZXJlIG1hZGUgYmVmb3JlIGluZGl2aWR1YWxzIHdlcmUgcHJlc2VydmVkIGluIGV0aGFub2wuIFdlIGV4Y2x1ZGVkIGRhdGEgZm9yIGByIGRpbShleGNsdWRlZClbMV1gIGluZGl2aWR1YWxzLCBkZXRhaWxlZCBiZWxvdy4gVGhlc2UgaW5kaXZpZHVhbHMgaGFkIGVpdGhlciB2ZXJ5IGxvdyBDVG1heCBvciB3ZXJlLCB1cG9uIHJlLWV4YW1pbmF0aW9uIG9mIHBob3RvZ3JhcGhzLCBpZGVudGlmaWVkIGFzIGp1dmVuaWxlcyBpbnN0ZWFkIG9mIG1hdHVyZSBmZW1hbGVzLiAgCgpgYGB7ciBleGNsdWRlZC1pbmRzfQpleGNsdWRlZCAlPiUgCiAgc2VsZWN0KHJlZ2lvbiwgc2l0ZSwgc2Vhc29uLCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHksIHJlcGxpY2F0ZSwgdHViZSwgY3RtYXgsIHNpemUpICU+JSAKICBrbml0cjo6a2FibGUoYWxpZ24gPSAiYyIpCmBgYAoKQ3JpdGljYWwgdGhlcm1hbCBtYXhpbWEgKENUbWF4KSB3YXMgbWVhc3VyZWQgdXNpbmcgYSBjdXN0b20gc2V0dXAuIFRoZSBtZXRob2QgdXNlcyBhIHN0YW5kYXJkIGR5bmFtaWMgcmFtcGluZyBhc3NheSB0byBkZXRlcm1pbmUgdGhlIG1heGltdW0gdGVtcGVyYXR1cmUgaW5kaXZpZHVhbHMgY291bGQgc3VzdGFpbiBub3JtYWwgZnVuY3Rpb25pbmcuIFRoaXMgZGlmZmVycyBmcm9tIGxldGhhbCB0ZW1wZXJhdHVyZXMsIGFuZCBpbmRlZWQsIGFsbCBpbmRpdmlkdWFscyBvYnNlcnZlZCBzbyBmYXIgcmVjb3ZlcmVkIGZvbGxvd2luZyB0aGUgYXNzYXkuCgpJbmRpdmlkdWFscyB3ZXJlIHJlc3RlZCBmb3Igb25lIGhvdXIgYWZ0ZXIgY29sbGVjdGlvbiBiZWZvcmUgdGhlIGFzc2F5LiBEdXJpbmcgdGhlIGFzc2F5LCBjb3BlcG9kcyB3ZXJlIGhlbGQgaW4gMC4yIHVtIGZpbHRlcmVkIHNlYXdhdGVyLCBhZGp1c3RlZCB0byBtYXRjaCB0aGUgc2FsaW5pdHkgYXQgdGhlIHRpbWUgb2YgY29sbGVjdGlvbiB3aXRoIGJvdHRsZWQgc3ByaW5nIHdhdGVyLiBEdXJpbmcgdGhlIGFzc2F5LCBzZXZlcmFsICdjb250cm9sJyBpbmRpdmlkdWFscyB3ZXJlIG1haW50YWluZWQgaW4gdGhpcyBhZGp1c3RlZCBzYWxpbml0eSBzb2x1dGlvbiwgYnV0IGRpZCBub3QgZXhwZXJpZW5jZSB0aGUgdGVtcGVyYXR1cmUgcmFtcCwgdG8gZW5zdXJlIHRoYXQgdGhlcmUgd2FzIG5vIGJhY2tncm91bmQgbW9ydGFsaXR5LgoKU2hvd24gYmVsb3cgYXJlIHRoZSBtZWFzdXJlZCBDVG1heCB2YWx1ZXMuIE5vdGU6IENUbWF4IHZhbHVlcyBmb3IgdGhlIGVhcmx5IHNlYXNvbiBLZXkgTGFyZ28gY29wZXBvZHMgd2VyZSBjb2xsZWN0ZWQgYXQgdGhlIGVuZCBvZiBGZWJydWFyeSAyMDIzIGFzIHBhcnQgb2YgYSBzZXBhcmF0ZSBwcm9qZWN0LiBCb2R5IHNpemUgdmFsdWVzIHdlcmUgbm90IG1lYXN1cmVkIGR1cmluZyB0aGlzIHByb2plY3QsIG5vciB3ZXJlIGNvcGVwb2RzIGluZGl2aWR1YWxseSBwcmVzZXJ2ZWQgYWZ0ZXIgdGhlIGV4cGVyaW1lbnRzLiBUaGVzZSBlYXJseSBzZWFzb24gQ1RtYXggdmFsdWVzIGFyZSBpbmNsdWRlZCBhcyBhIHBvaW50IG9mIGNvbXBhcmlzb24uIEluZGl2aWR1YWwgbWVhc3VyZW1lbnRzIGFyZSBzaG93biBpbiBzbWFsbCBwb2ludHMgZm9yIGVhY2ggY29sbGVjdGlvbi4gVGhlIGxhcmdlIHBvaW50IGluZGljYXRlcyB0aGUgbWVkaWFuIHZhbHVlLiAKCmBgYHtyIHNlYXNvbmFsLWN0LW1heH0KbWVhbl9jdG1heCA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCkgJT4lIAogIHN1bW1hcml6ZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIG1lZGlhbl9jdG1heCA9IG1lZGlhbihjdG1heCkpCgpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fY3RtYXgpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKYGBge3IgZG95LWN0LW1heH0KZ2dwbG90KGZpbHRlcihmdWxsX2RhdGEsIHNpdGUgIT0gIktleSBMYXJnbyIpLCBhZXMoeCA9IGRveSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGZpbHRlcihtZWFuX2N0bWF4LCBzaXRlICE9ICJLZXkgTGFyZ28iKSwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4LCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKG1lYW5fY3RtYXgsIHNpdGUgIT0gIktleSBMYXJnbyIpLCAKICAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIGN0bWF4LWluZC1wb3BzLXNlYXNvbiwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBzZWFzb24sIHkgPSBjdG1heCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZmFjZXRfd3JhcCgufnNpdGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4LCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMywgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBtZWFuX2N0bWF4LCAKICAgICAgICAgICAgYWVzKHkgPSBjb2xsZWN0aW9uX3RlbXAsIGdyb3VwID0gc2l0ZSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICAgICAgICAgICBsaW5ld2lkdGggPSAyLAogICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC44KSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9jdG1heCwgCiAgIyAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAjICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgIyAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIGN0bWF4LWluZC1wb3BzLWRveSwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBkb3ksIHkgPSBjdG1heCwgY29sb3VyID0gc2l0ZSkpICsgCiAgZmFjZXRfd3JhcCgufnNpdGUsIHNjYWxlcyA9ICJmcmVlIikgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fY3RtYXgsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDMsIGFscGhhID0gMC41KSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9jdG1heCwgCiAgICAgICAgICAgIGFlcyh5ID0gY29sbGVjdGlvbl90ZW1wLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMiwKICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICMgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgIyAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICMgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgoKIyMgV2FybWluZyB0b2xlcmFuY2UKCldhcm1pbmcgdG9sZXJhbmNlIHdhcyBjYWxjdWxhdGVkIGFzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gbWVhc3VyZWQgQ1RtYXggdmFsdWVzIGFuZCB0aGUgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZS4gTG93ZXIgd2FybWluZyB0b2xlcmFuY2UgdmFsdWVzIGluZGljYXRlIHRoYXQgcG9wdWxhdGlvbnMgd2VyZSBuZWFyZXIgdG8gdGhlaXIgdXBwZXIgdGhlcm1hbCBsaW1pdHMsIGFuZCBtYXkgdGhlcmVmb3JlIGJlIG1vcmUgdnVsbmVyYWJsZSB0byBhZGRpdGlvbmFsIHdhcm1pbmcuIAoKYGBge3Igc2Vhc29uYWwtd2FybWluZy10b2x9Cm1lYW5fd3QgPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUsIHNlYXNvbikgJT4lIAogIHN1bW1hcml6ZShtZWFuX3d0ID0gbWVhbih3YXJtaW5nX3RvbCksCiAgICAgICAgICAgIG1lZGlhbl93dCA9IG1lZGlhbih3YXJtaW5nX3RvbCkpCgpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IHdhcm1pbmdfdG9sLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IG1lYW5fd3QsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl93dCwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fd3QsIAogICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fd3QpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiV2FybWluZyBUb2xlcmFuY2UgKMKwQykiLAogICAgICAgeCA9ICJTZWFzb24iKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKIyMgQm9keSBTaXplCgpGb2xsb3dpbmcgdGhlIENUbWF4IGFzc2F5LCBpbmRpdmlkdWFscyB3ZXJlIHBob3RvZ3JhcGhlZCBmb3IgYm9keSBzaXplIG1lYXN1cmVtZW50cy4gUHJvc29tZSBsZW5ndGhzIHdlcmUgbWVhc3VyZWQgZnJvbSB0aGVzZSBwaG90b2dyYXBocyB1c2luZyBhIHNjYWxlIG1pY3JvbWV0ZXIgYW5kIHRoZSBzb2Z0d2FyZSBJbWFnZUouIFRoZXNlIG1lYXN1cmVtZW50cyBhcmUgc2hvd24gYmVsb3cuCgpgYGB7ciBzZWFzb25hbC1ib2R5LXNpemV9Cm1lYW5fc2l6ZSA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgc2Vhc29uLCBkb3ksIGNvbGxlY3Rpb25fdGVtcCkgJT4lIAogIHN1bW1hcml6ZShtZWFuX3NpemUgPSBtZWFuKHNpemUpLAogICAgICAgICAgICBtZWRpYW5fc2l6ZSA9IG1lZGlhbihzaXplKSkKCmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gc2Vhc29uLCB5ID0gc2l6ZSwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBtZWFuX3NpemUsIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9zaXplLCAKICAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX3NpemUpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgpgYGB7ciBkb3ktYm9keS1zaXplfQpnZ3Bsb3QoZHJvcF9uYShmdWxsX2RhdGEsIHNpemUpLCBhZXMoeCA9IGRveSwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShkYXRhID0gZHJvcF9uYShtZWFuX3NpemUsIG1lYW5fc2l6ZSksIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xLCBqaXR0ZXIuaGVpZ2h0ID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9kZ2Uud2lkdGggPSAwLjQpLAogICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZHJvcF9uYShtZWFuX3NpemUsIG1lYW5fc2l6ZSksIAogICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSksCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCAobW0pIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIHNpemUtaW5kLXBvcHMtc2Vhc29uLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoLn5zaXRlKSArIAogIGdlb21fbGluZShkYXRhID0gbWVhbl9zaXplLCAKICAgICAgICAgICAgYWVzKHkgPSBtZWRpYW5fc2l6ZSwgZ3JvdXAgPSBzaXRlKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDMsIGFscGhhID0gMC41KSArIAogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjEsIGppdHRlci5oZWlnaHQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2RnZS53aWR0aCA9IDAuNCksCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKyAKICAjIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5fY3RtYXgsIAogICMgICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9jdG1heCksCiAgIyAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjQpLAogICMgICAgICAgICAgICBzaXplID0gNCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiUHJvc29tZSBMZW5ndGggKG1tKSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIGxlZ2VuZC50aXRsZS5hbGlnbiA9IDAuMTI1KQpgYGAKCmBgYHtyIHNpemUtaW5kLXBvcHMtZG95LCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpnZ3Bsb3QoZHJvcF9uYShmdWxsX2RhdGEsIHNpemUpLCBhZXMoeCA9IGRveSwgeSA9IHNpemUsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoLn5zaXRlKSArIAogIGdlb21fbGluZShkYXRhID0gZHJvcF9uYShtZWFuX3NpemUsIG1lYW5fc2l6ZSksIAogICAgICAgICAgICBhZXMoeSA9IG1lZGlhbl9zaXplLCBncm91cCA9IHNpdGUpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC40KSwKICAgICAgICAgICAgbGluZXdpZHRoID0gMywgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgaml0dGVyLmhlaWdodCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvZGdlLndpZHRoID0gMC40KSwKICAgICAgICAgICAgIGFscGhhID0gMC44KSArIAogICMgZ2VvbV9wb2ludChkYXRhID0gbWVhbl9jdG1heCwgCiAgIyAgICAgICAgICAgIGFlcyh5ID0gbWVkaWFuX2N0bWF4KSwKICAjICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCksCiAgIyAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCAobW0pIiwKICAgICAgIHggPSAiU2Vhc29uIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgICAgICAgbGVnZW5kLnRpdGxlLmFsaWduID0gMC4xMjUpCmBgYAoKIyMjIFNhbGluaXR5IFBhaXIgQ29tcGFyaXNvbnMgCgpgYGB7ciBzYWwtcGFpci10cmFpdHN9CnNhbF9jb21wX2N0bWF4X3Bsb3QgPSBzYWxfY29tcHMgJT4lIAogIGdncGxvdChhZXMoeCA9IHNhbGluaXR5LCB5ID0gY3RtYXgsIGNvbG91ciA9IHNlYXNvbiwgZ3JvdXAgPSBzZWFzb24pKSArIAogIGZhY2V0X3dyYXAocmVnaW9ufi4pICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjIpKSArIAogICNnZW9tX2xpbmUoc2l6ZSA9IDEuNSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICB4ID0gIiIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCgpzYWxfY29tcF9zaXplX3Bsb3QgPSBzYWxfY29tcHMgJT4lIAogIGdncGxvdChhZXMoeCA9IHNhbGluaXR5LCB5ID0gc2l6ZSwgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsgCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCAKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjIpKSArIAogICNnZW9tX2xpbmUoc2l6ZSA9IDEuNSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNlYXNvbl9jb2xzKSArIAogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCAobW0pIiwKICAgICAgIHggPSAiIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCmdnYXJyYW5nZShzYWxfY29tcF9jdG1heF9wbG90LCBzYWxfY29tcF9zaXplX3Bsb3QsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKCiMjIwoKc2FsX2NvbXBfY3RtYXgubW9kZWwgPSBsbShjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCwgZGF0YSA9IHNhbF9jb21wcykKIyBzdW1tYXJ5KGN0bWF4X3RlbXAubW9kZWwpCiMgY2FyOjpBbm92YShjdG1heF90ZW1wLm1vZGVsKQpzYWxfY29tcF9jdG1heF9yZXNpZHMgPSByZXNpZHVhbHMoc2FsX2NvbXBfY3RtYXgubW9kZWwpCgpzYWxfY29tcF9zaXplLm1vZGVsID0gbG0oc2l6ZSB+IGNvbGxlY3Rpb25fdGVtcCwgZGF0YSA9IHNhbF9jb21wcykKIyBzdW1tYXJ5KHNpemVfdGVtcC5tb2RlbCkKIyBjYXI6OkFub3ZhKHNpemVfdGVtcC5tb2RlbCkKc2FsX2NvbXBfc2l6ZV9yZXNpZHMgPSByZXNpZHVhbHMoc2FsX2NvbXBfc2l6ZS5tb2RlbCkKCnNhbF9jb21wX2N0bWF4X3Jlc2lkX3Bsb3QgPSBzYWxfY29tcHMgJT4lCiAgbXV0YXRlKGN0bWF4X3Jlc2lkcyA9IHNhbF9jb21wX2N0bWF4X3Jlc2lkcywKICAgICAgICAgc2l6ZV9yZXNpZHMgPSBzYWxfY29tcF9zaXplX3Jlc2lkcykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBjdG1heF9yZXNpZHMsIGNvbG91ciA9IHNlYXNvbiwgZ3JvdXAgPSBzZWFzb24pKSArCiAgZmFjZXRfd3JhcChyZWdpb25+LikgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKwogICNnZW9tX2xpbmUoc2l6ZSA9IDEuNSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2Vhc29uX2NvbHMpICsKICBsYWJzKHkgPSAiQ1RtYXggXG5SZXNpZHVhbHMiLAogICAgICAgeCA9ICIiKSArCiAgdGhlbWVfbWF0dF9mYWNldHMoYmFzZV9zaXplID0gMTQpCgpzYWxfY29tcF9zaXplX3Jlc2lkX3Bsb3QgPSBzYWxfY29tcHMgJT4lCiAgbXV0YXRlKGN0bWF4X3Jlc2lkcyA9IHNhbF9jb21wX2N0bWF4X3Jlc2lkcywKICAgICAgICAgc2l6ZV9yZXNpZHMgPSBzYWxfY29tcF9zaXplX3Jlc2lkcykgJT4lCiAgZ2dwbG90KGFlcyh4ID0gc2FsaW5pdHksIHkgPSBzaXplX3Jlc2lkcywgY29sb3VyID0gc2Vhc29uLCBncm91cCA9IHNlYXNvbikpICsKICBmYWNldF93cmFwKHJlZ2lvbn4uKSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArCiAgI2dlb21fbGluZShzaXplID0gMS41KSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzZWFzb25fY29scykgKwogIGxhYnMoeSA9ICJQcm9zb21lIExlbmd0aCBcblJlc2lkdWFscyIsCiAgICAgICB4ID0gIiIpICsKICB0aGVtZV9tYXR0X2ZhY2V0cyhiYXNlX3NpemUgPSAxNCkKCiNnZ2FycmFuZ2Uoc2FsX2NvbXBfY3RtYXhfcmVzaWRfcGxvdCwgc2FsX2NvbXBfc2l6ZV9yZXNpZF9wbG90LCBucm93ID0gMiwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJyaWdodCIpCmBgYAoKCiMjIFRyYWl0IENvcnJlbGF0aW9ucwoKV2UgZXhwZWN0IHRoYXQgY29sbGVjdGlvbnMgZnJvbSB3YXJtZXIgd2F0ZXJzIHNob3VsZCB5aWVsZCBjb3BlcG9kcyB3aXRoIGhpZ2hlciB0aGVybWFsIGxpbWl0cyBhbmQgc21hbGxlciBib2R5IHNpemVzLgoKYGBge3IgdGVtcC1jb3JzLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9Nn0KY3RtYXhfdGVtcF9wbG90ID0gZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heCkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwgCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgpzaXplX3RlbXBfcGxvdCA9IGdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwgCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgp3dF90ZW1wX3Bsb3QgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IHdhcm1pbmdfdG9sKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiV2FybWluZyBUb2xlcmFuY2UgKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2UoY3RtYXhfdGVtcF9wbG90LCB3dF90ZW1wX3Bsb3QsIHNpemVfdGVtcF9wbG90LCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gImJvdHRvbSIsIG5yb3cgPSAxKQpgYGAKCmBgYHtyIGluY2x1ZGUgPSBGfQpnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4KSkgKyAKICBmYWNldF93cmFwKC5+c2l0ZSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNpdGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmdncGxvdChmdWxsX2RhdGEsIGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gc2l6ZSkpICsgCiAgZmFjZXRfd3JhcCgufnNpdGUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIsIAogICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwgCiAgICAgICAgICAgICBzaXplID0gMiwgYWxwaGEgPSAwLjcpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYAoKT2YgcGFydGljdWxhciBpbnRlcmVzdCBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJvc29tZSBsZW5ndGggYW5kIENUbWF4LiBJbiBtYW55IGNhc2VzLCBsYXJnZXIgYm9keSBzaXplcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGNvbGQgYWRhcHRhdGlvbi9hY2NsaW1hdGlvbi4gV2UgbWF5IHRoZXJlZm9yZSBzZWUgdGhpcyBwYXR0ZXJuIGVtZXJnZSBhY3Jvc3MgcG9wdWxhdGlvbnMgb3Igc2Vhc29ucy4gSWYgcG9wdWxhdGlvbnMgY29udGFpbiBhIG1peCBvZiBjb2xkLSBhbmQgd2FybS1hZGFwdGVkIGdlbm90eXBlcywgaG93ZXZlciwgd2UgbWlnaHQgYWxzbyBzZWUgdGhpcyByZWxhdGlvbnNoaXAgZW1lcmdlICoqd2l0aGluKiogaW5kaXZpZHVhbCBjb2xsZWN0aW9ucy4gU2hvd24gYmVsb3cgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByb3NvbWUgbGVuZ3RoIGFuZCBDVG1heCBmb3IgdGhlIGluZGl2aWR1YWxzIG1lYXN1cmVkIHRodXMgZmFyLiBJbmRpdmlkdWFsIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGVhY2ggc2l0ZSBhcmUgYWxzbyBpbmNsdWRlZC4gTm90ZSB0aGF0IHJhdyBDVG1heCBhbmQgYm9keSBzaXplIHZhbHVlcyBhcmUgc2hvd24sIHJhdGhlciB0aGFuIG1ldHJpY3MgbGlrZSByZXNpZHVhbHMgZnJvbSBhIHN0YXRpc3RpY2FsIG1vZGVsIGNvcnJlY3RpbmcgZm9yIHZhcmlhdGlvbiBpbiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlLgoKYGBge3IgY3RtYXgtdnMtc2l6ZSwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9MTB9CnVuaXZlcnNhbF9zaXplID0gZnVsbF9kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzaXplLCB5ID0gY3RtYXgpKSArIAogICMgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIGN0bWF4ID4gMzEpLCAKICAjICAgICAgICAgICAgIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4KSwKICAjICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIAogICMgICAgICAgICAgICAgY29sb3VyID0gImdyZXk2MCIsIAogICMgICAgICAgICAgICAgc2UgPSBGLAogICMgICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTcwIikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgeCA9ICIiKSArCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCnBvcF9zaXplID0gZnVsbF9kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzaXplLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNpdGUsIGdyb3VwID0gc2Vhc29uKSkgKyAKICBmYWNldF93cmFwKHNpdGV+LikgKyAKICAjIGdlb21fc21vb3RoKGRhdGEgPSBmaWx0ZXIoZnVsbF9kYXRhLCBjdG1heCA+IDMxKSwgCiAgIyAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgIyAgICAgICAgICAgICBtZXRob2QgPSAibG0iLCAKICAjICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5NjAiLCAKICAjICAgICAgICAgICAgIHNlID0gRiwKICAjICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMS4zLCBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCwgZ3JvdXAgPSBzaXRlKSwgCiAgICAgICAgICAgICAgY29sb3VyID0gImdyZXk3MCIsIG1ldGhvZCA9ICJsbSIsIHNlID0gRikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLjYsIDAuOCwgMSkpICsgCiAgbGFicyh5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIHggPSAiUHJvc29tZSBMZW5ndGggKG1tKSIpICsKICB0aGVtZV9tYXR0KGJhc2Vfc2l6ZSA9IDE0KSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2UodW5pdmVyc2FsX3NpemUsIHBvcF9zaXplLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gIm5vbmUiLCBucm93ID0gMikKYGBgCgpgYGB7ciBpbmNsdWRlID0gRn0KZmlsdGVyZWRfZGF0YSA9IGZ1bGxfZGF0YSAlPiUgCiAgZHJvcF9uYShzaXplLCBjdG1heCkKCmN0bWF4X3NpemUubW9kZWwgPSBsbShjdG1heCB+IHNpemUgKyBzaXRlLCBkYXRhID0gZmlsdGVyZWRfZGF0YSkKY2FyOjpBbm92YShjdG1heF9zaXplLm1vZGVsKQoKY3RtYXhfdGVtcC5tb2RlbCA9IGxtKGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wICsgc2l0ZSwgZGF0YSA9IGZpbHRlcmVkX2RhdGEpCmN0bWF4X3Jlc2lkcyA9IHJlc2lkdWFscyhjdG1heF90ZW1wLm1vZGVsKQoKc2l6ZV90ZW1wLm1vZGVsID0gbG0oc2l6ZSB+IGNvbGxlY3Rpb25fdGVtcCArIHNpdGUsIGRhdGEgPSBmaWx0ZXJlZF9kYXRhKQpzaXplX3Jlc2lkcyA9IHJlc2lkdWFscyhzaXplX3RlbXAubW9kZWwpCgp1bml2ZXJzYWxfcmVzaWRzID0gZmlsdGVyZWRfZGF0YSAlPiUgCiAgbXV0YXRlKGN0bWF4X3Jlc2lkcyA9IGN0bWF4X3Jlc2lkcywKICAgICAgICAgc2l6ZV9yZXNpZHMgPSBzaXplX3Jlc2lkcykgCgphbGxfcmVzaWRzID0gZ2dwbG90KHVuaXZlcnNhbF9yZXNpZHMsIGFlcyh4ID0gc2l6ZV9yZXNpZHMsIHkgPSBjdG1heF9yZXNpZHMpKSArIAogICMgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIGN0bWF4ID4gMzEpLCAKICAjICAgICAgICAgICAgIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4KSwKICAjICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsIAogICMgICAgICAgICAgICAgY29sb3VyID0gImdyZXk2MCIsIAogICMgICAgICAgICAgICAgc2UgPSBGLAogICMgICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTcwIikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzaXRlKSwKICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiQ1RtYXggUmVzaWR1YWxzIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX21hdHQoYmFzZV9zaXplID0gMTQpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpwb3BfcmVzaWRzID0gZ2dwbG90KHVuaXZlcnNhbF9yZXNpZHMsIGFlcyh4ID0gc2l6ZV9yZXNpZHMsIHkgPSBjdG1heF9yZXNpZHMsIGNvbG91ciA9IHNpdGUsIGdyb3VwID0gc2Vhc29uKSkgKyAKICBmYWNldF93cmFwKHNpdGV+LikgKyAKICAjIGdlb21fc21vb3RoKGRhdGEgPSBmaWx0ZXIoZnVsbF9kYXRhLCBjdG1heCA+IDMxKSwgCiAgIyAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgIyAgICAgICAgICAgICBtZXRob2QgPSAibG0iLCAKICAjICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5NjAiLCAKICAjICAgICAgICAgICAgIHNlID0gRiwKICAjICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMS4zLCBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChhZXMoeCA9IHNpemVfcmVzaWRzLCB5ID0gY3RtYXhfcmVzaWRzLCBncm91cCA9IHNpdGUpLCAKICAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTcwIiwgbWV0aG9kID0gImxtIiwgc2UgPSBGKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCBSZXNpZHVhbHMiLAogICAgICAgeCA9ICJQcm9zb21lIExlbmd0aCBSZXNpZHVhbHMiKSArCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKZ2dhcnJhbmdlKGFsbF9yZXNpZHMsIHBvcF9yZXNpZHMsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAibm9uZSIsIG5yb3cgPSAyKQpgYGAKCmBgYHtyIGN0bWF4LW1vZGVsLCBpbmNsdWRlID0gRn0KY3RtYXgubW9kZWwgPSBsbWU0OjpsbWVyKGRhdGEgPSBmdWxsX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICBjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCAqIHNpemUgKyAoMXxzaXRlKSkKCnN1bW1hcnkoY3RtYXgubW9kZWwpCmNhcjo6QW5vdmEoY3RtYXgubW9kZWwpCmBgYAoKCiMjIFRyYWl0IFZhcmlhYmlsaXR5CgpTaG93biBiZWxvdyBpcyB0aGUgdHJhaXQgdmFyaWF0aW9uIChyYW5nZXMpIGZvciBlYWNoIHNpdGUuIFJhbmdlcyBhcmUgY2FsY3VsYXRlZCBmb3IgZWFjaCBzZWFzb24gc2VwYXJhdGVseS4KCmBgYHtyIHRyYWl0LXJhbmdlLXBsb3R9CnRyYWl0X3JhbmdlcyA9IGZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSwgc2Vhc29uLCBjb2xsZWN0aW9uX3RlbXAsIGNvbGxlY3Rpb25fc2FsaW5pdHksIGRveSwgbGF0KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fY3RtYXggPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgY3RtYXhfcmFuZ2UgPSBtYXgoY3RtYXgpIC0gbWluKGN0bWF4KSwKICAgICAgICAgICAgY3RtYXhfdmFyID0gdmFyKGN0bWF4KSwKICAgICAgICAgICAgbWVhbl9zaXplID0gbWVhbihzaXplKSwKICAgICAgICAgICAgc2l6ZV9yYW5nZSA9IG1heChzaXplKSAtIG1pbihzaXplKSwKICAgICAgICAgICAgc2l6ZV92YXIgPSB2YXIoc2l6ZSkpICU+JSAKICBtdXRhdGUocHJvcF9jdG1heF9yYW5nZSA9IGN0bWF4X3JhbmdlIC8gbWVhbl9jdG1heCwKICAgICAgICAgcHJvcF9zaXplX3JhbmdlID0gc2l6ZV9yYW5nZSAvIG1lYW5fc2l6ZSkKCmN0bWF4X3JhbmdlX3RlbXAgPSBnZ3Bsb3QodHJhaXRfcmFuZ2VzLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4X3JhbmdlLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCBSYW5nZSAowrBDKSIsCiAgICAgICB4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmN0bWF4X3Zhcl90ZW1wID0gZ2dwbG90KHRyYWl0X3JhbmdlcywgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heF92YXIsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzaXRlX2NvbHMpICsgCiAgbGFicyh5ID0gIkNUbWF4IFJhbmdlICjCsEMpIiwKICAgICAgIHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKc2l6ZV9yYW5nZV90ZW1wID0gZ2dwbG90KHRyYWl0X3JhbmdlcywgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBzaXplX3JhbmdlLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJTaXplIFJhbmdlIChtbSkiLAogICAgICAgeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpzaXplX3Zhcl90ZW1wID0gZ2dwbG90KHRyYWl0X3JhbmdlcywgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBzaXplX3ZhciwgY29sb3VyID0gc2l0ZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHkgPSAiU2l6ZSBSYW5nZSAobW0pIiwKICAgICAgIHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKZ2dhcnJhbmdlKGN0bWF4X3JhbmdlX3RlbXAsIHNpemVfcmFuZ2VfdGVtcCwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKCkNoYW5nZXMgaW4gdHJhaXQgdmFyaWFuY2UgbWF5IGJlIGluZGljYXRpdmUgb2YgcGhlbm90eXBpYyBzZWxlY3Rpb24uIElmIHNlbGVjdGlvbiAoYXMgb3Bwb3NlZCB0byBhY2NsaW1hdGlvbikgYXJlIGRyaXZpbmcgc2Vhc29uYWwgY2hhbmdlcywgd2UgbWF5IGV4cGVjdCB0byBzZWUgYSByZWR1Y3Rpb24gaW4gdmFyaWFuY2UgaW4gdGhlIHBlYWsgc2FtcGxlcyByZWxhdGl2ZSB0byB0aGUgZWFybHkgc2Vhc29uIHNhbXBsZXMuIE5vdGUgdGhhdCBlYXJseSBzZWFzb24gY29sbGVjdGlvbiB0ZW1wZXJhdHVyZXMgdGhpcyB5ZWFyIHdlcmUgaGlnaGVyIHRoYW4gZXhwZWN0ZWQsIGRyaXZlbiBieSBmYWlybHkgc3Ryb25nIGhlYXR3YXZlcyBpbiB0aGUgTm9ydGggQXRsYW50aWMuICAgIAoKYGBge3Igc2Vhc29uLXZhcn0KZ2dwbG90KHRyYWl0X3JhbmdlcywgYWVzKHggPSBzZWFzb24sIHkgPSBjdG1heF92YXIsIGNvbG91ciA9IHNpdGUpKSArIAogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBzaXRlKSwgCiAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEuNSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeSA9ICJDVG1heCBWYXJpYW5jZSIsCiAgICAgICB4ID0gIlNlYXNvbiIpICsKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKYGBgCgpgYGB7ciB2YXItY2hhbmdlLXRlbXAtY2hhbmdlLCBpbmNsdWRlID0gRn0KdmFyX2NoYW5nZV9kYXRhID0gdHJhaXRfcmFuZ2VzICU+JSAgCiAgbXV0YXRlKG1lYW5fd3QgPSBtZWFuX2N0bWF4IC0gY29sbGVjdGlvbl90ZW1wKSAlPiUgCiAgZ3JvdXBfYnkoc2l0ZSkgJT4lIAogIGFycmFuZ2UoZG95KSAlPiUgIAogIG11dGF0ZSh0ZW1wX2NoYW5nZSA9IGNvbGxlY3Rpb25fdGVtcCAtIGxhZyhjb2xsZWN0aW9uX3RlbXApLAogICAgICAgICBjdG1heF9jaGFuZ2UgPSBtZWFuX2N0bWF4IC0gbGFnKG1lYW5fY3RtYXgpLAogICAgICAgICB3dF9jaGFuZ2UgPSBtZWFuX3d0IC0gbGFnKG1lYW5fd3QpLAogICAgICAgICB2YXJfY2hhbmdlID0gY3RtYXhfdmFyIC0gbGFnKGN0bWF4X3ZhcikpICU+JSAgCiAgc2VsZWN0KHNpdGUsIHNlYXNvbiwgZG95LCBsYXQsIHRlbXBfY2hhbmdlLCB2YXJfY2hhbmdlLCBjdG1heF9jaGFuZ2UsIHd0X2NoYW5nZSkKCmdncGxvdCh2YXJfY2hhbmdlX2RhdGEsIGFlcyh4ID0gd3RfY2hhbmdlLCB5ID0gdmFyX2NoYW5nZSwgY29sb3VyID0gc2l0ZSkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiV2FybWluZyBUb2xlcmFuY2UgQ2hhbmdlICjCsEMpIiwKICAgICAgIHkgPSAiQ2hhbmdlIGluIENUbWF4IFZhcmlhbmNlIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICBsZWdlbmQudGl0bGUuYWxpZ24gPSAwLjEyNSkKCmdncGxvdCh0cmFpdF9yYW5nZXMsIGFlcyh4ID0gc2l6ZV9yYW5nZSwgeSA9IHNpemVfdmFyKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aCgpICsKICB0aGVtZV9tYXR0KCkKYGBgCgojIyBDb21wYXJpbmcgcmF0ZXMgb2YgY2hhbmdlIChIYWxkYW5lcykKQm90aCBDVG1heCBhbmQgYm9keSBzaXplIHZhcmllZCBiZXR3ZWVuIHNpdGVzIGFuZCBhY3Jvc3Mgc2Vhc29ucy4gSXQgY2FuIGJlIGRpZmZpY3VsdCB0byBkaXJlY3RseSBjb21wYXJlIHRoZXNlIHR3byB0cmFpdHMuIFdlIHRha2UgdHdvIGFwcHJvYWNoZXMgdG8gZWFzZSB0aGlzIGNvbXBhcmlzb24uIApTaG93biBiZWxvdyBpcyBhIGNvbXBhcmlzb24gb2YgdGhlIHNsb3BlcyBmcm9tIHRoZSB0cmFpdCByZWdyZXNzaW9ucyBhZ2FpbnN0IGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUgZm9yIGVhY2ggcG9wdWxhdGlvbiwgc3RhbmRhcmRpemVkIGJ5IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHRyYWl0IGZvciBlYWNoIHBvcHVsYXRpb24gKGFjcm9zcyBhbGwgY29sbGVjdGlvbnMpLiBUaGlzIHByZXNlbnRzIGNoYW5nZSBwZXIgZGVncmVlIGNoYW5nZSBpbiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIGluIHVuaXRzIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgZm9yIGJvdGggQ1RtYXggYW5kIGJvZHkgc2l6ZS4KCmBgYHtyfQphZGpfc2xvcGVzID0gZnVsbF9kYXRhICU+JSAKICBncm91cF9ieShzaXRlLCBsYXQpICU+JSAKICBhcnJhbmdlKGRveSkgJT4lICAKICBmaWx0ZXIoc2l0ZSAhPSAiS2V5IExhcmdvIikgJT4lCiAgc3VtbWFyaXplKCJjdG1heF9zbG9wZSIgPSBjb2VmKGxtKGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wKSlbImNvbGxlY3Rpb25fdGVtcCJdLCAKICAgICAgICAgICAgIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCksCiAgICAgICAgICAgICJjdG1heF9zZCIgPSBzZChjdG1heCksCiAgICAgICAgICAgICJzaXplX3Nsb3BlIiA9IGNvZWYobG0oc2l6ZSB+IGNvbGxlY3Rpb25fdGVtcCkpWyJjb2xsZWN0aW9uX3RlbXAiXSwgCiAgICAgICAgICAgICJtZWFuX3NpemUiID0gbWVhbihzaXplKSwKICAgICAgICAgICAgInNpemVfc2QiID0gc2Qoc2l6ZSksIAogICAgICAgICAgICAidGVtcF9yYW5nZSIgPSBtYXgoY29sbGVjdGlvbl90ZW1wKSAtIG1pbihjb2xsZWN0aW9uX3RlbXApKSAlPiUgIAogIGRyb3BfbmEoKSAlPiUgCiAgbXV0YXRlKGFkal9jdG1heF9zbG9wZSA9IGN0bWF4X3Nsb3BlIC8gY3RtYXhfc2QsCiAgICAgICAgIGFkal9zaXplX3Nsb3BlID0gc2l6ZV9zbG9wZSAvIHNpemVfc2QpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJhZGpfIiksIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJzbG9wZV90eXBlIiwKICAgICAgICAgICAgICAgbmFtZXNfcHJlZml4ID0gImFkal8iLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAic2xvcGUiKQoKIyBnZ3Bsb3QoYWRqX3Nsb3BlcywgYWVzKHggPSBsYXQsIHkgPSB0ZW1wX3JhbmdlKSkgKyAKIyAgIGdlb21fcG9pbnQoKSArIAojICAgdGhlbWVfbWF0dCgpCgpnZ3Bsb3QoYWRqX3Nsb3BlcywgYWVzKHggPSBzbG9wZV90eXBlLCB5ID0gYWJzKHNsb3BlKSwgCiAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBzaXRlLCBjb2xvdXIgPSBzaXRlKSkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKSGFsZGFuZXMgYXJlIGEgc2ltaWxhciB1bml0LCByZXByZXNlbnRpbmcgY2hhbmdlIGluIHVuaXRzIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgcGVyIGdlbmVyYXRpb24uIFRoaXMgY2FuIGJlIGEgdXNlZnVsIG1ldHJpYyBmb3IgY29tcGFyaW5nIGFjcm9zcyB0cmFpdHMsIGVzcGVjaWFsbHkgYXMgdGhlIG51bWJlciBvZiBnZW5lcmF0aW9ucyBjb3ZlcmVkIGJ5IG91ciBzYW1wbGluZyBwZXJpb2QgbGlrZWx5IHZhcmllcyBhY3Jvc3MgcG9wdWxhdGlvbnMuIFRoZSBjYWxjdWxhdGlvbiBvZiBoYWxkYW5lcyBpcyB0YWtlbiBmcm9tIEhlbmRyeSBhbmQgS2lubmlzb24gKDE5OTkpLCB3aGljaCBpbiB0dXJuIGlzIGJhc2VkIG9uIHdvcmsgZnJvbSBHaW5nZXJpY2ggKDE5OTMpLiBXZSBlc3RpbWF0ZWQgdGhlIG51bWJlciBvZiBnZW5lcmF0aW9ucyBwYXNzZWQgYmV0d2VlbiBjb2xsZWN0aW9ucyB1c2luZyB0aGUgZW1waXJpY2FsIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRlbXBlcmF0dXJlIGFuZCBkZXZlbG9wbWVudCB0aW1lIGZyb20gX19fXy4gRm9yIGluaXRpYWwgZXN0aW1hdGVzLCB3ZSB1c2VkIGEgdGVtcGVyYXR1cmUgaGFsZndheSBpbiBiZXR3ZWVuIGNvbGxlY3Rpb25zLiAKCmBgYHtyIGhhbGRhbmUtY29tcC1wbG90LCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTl9CmVhcmx5X3BlYWsgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZWFzb24gJWluJSBjKCJlYXJseSIsICJwZWFrIikpICU+JSAKICBtdXRhdGUoc2Vhc29uID0gaWZfZWxzZShzZWFzb24gPT0gImVhcmx5IiwgIm9uZSIsICJ0d28iKSkgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBtdXRhdGUoY3RtYXhfc2RfcCA9IHNkKGN0bWF4KSwKICAgICAgICAgc2l6ZV9zZF9wID0gc2Qoc2l6ZSksIAogICAgICAgICB0ZW1wX2NoYW5nZSA9IG1heChjb2xsZWN0aW9uX3RlbXApIC0gbWluKGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgIGF2Z190ZW1wID0gKG1heChjb2xsZWN0aW9uX3RlbXApICsgbWluKGNvbGxlY3Rpb25fdGVtcCkpIC8gMiwKICAgICAgICAgZGF5c19wYXNzZWQgPSBtYXgoZG95KSAtIG1pbihkb3kpKSAlPiUgCiAgc2VsZWN0KHNpdGUsIGxhdCwgc2Vhc29uLCAKICAgICAgICAgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCwgCiAgICAgICAgIGN0bWF4LCBzaXplKSAlPiUKICBncm91cF9ieShzaXRlLCBsYXQsIHNlYXNvbiwgCiAgICAgICAgICAgY3RtYXhfc2RfcCwgc2l6ZV9zZF9wLCAKICAgICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkKSAlPiUgCiAgc3VtbWFyaXplKGN0bWF4ID0gbWVhbihjdG1heCksCiAgICAgICAgICAgIHNpemUgPSBtZWFuKHNpemUpKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoc2l0ZSwgbGF0LCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQpLCAKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc2Vhc29uLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGMoY3RtYXgsIHNpemUpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9ICJlYXJseV90b19wZWFrIikgJT4lICAKICBkcm9wX25hKCkKCnBlYWtfbGF0ZSA9IGZ1bGxfZGF0YSAlPiUgCiAgZmlsdGVyKHNlYXNvbiAlaW4lIGMoInBlYWsiLCAibGF0ZSIpKSAlPiUgCiAgbXV0YXRlKHNlYXNvbiA9IGlmX2Vsc2Uoc2Vhc29uID09ICJwZWFrIiwgIm9uZSIsICJ0d28iKSkgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBtdXRhdGUoY3RtYXhfc2RfcCA9IHNkKGN0bWF4KSwKICAgICAgICAgc2l6ZV9zZF9wID0gc2Qoc2l6ZSksIAogICAgICAgICB0ZW1wX2NoYW5nZSA9IGxhc3QoY29sbGVjdGlvbl90ZW1wKSAtIGZpcnN0KGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgIGF2Z190ZW1wID0gKG1heChjb2xsZWN0aW9uX3RlbXApICsgbWluKGNvbGxlY3Rpb25fdGVtcCkpIC8gMiwKICAgICAgICAgZGF5c19wYXNzZWQgPSBtYXgoZG95KSAtIG1pbihkb3kpKSAlPiUgCiAgc2VsZWN0KHNpdGUsIGxhdCwgc2Vhc29uLCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICB0ZW1wX2NoYW5nZSwgYXZnX3RlbXAsIGRheXNfcGFzc2VkLCAKICAgICAgICAgY3RtYXgsIHNpemUpICU+JQogIGdyb3VwX2J5KHNpdGUsIGxhdCwgc2Vhc29uLCBjdG1heF9zZF9wLCBzaXplX3NkX3AsIAogICAgICAgICAgIHRlbXBfY2hhbmdlLCBhdmdfdGVtcCwgZGF5c19wYXNzZWQpICU+JSAKICBzdW1tYXJpemUoY3RtYXggPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgc2l6ZSA9IG1lYW4oc2l6ZSkpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhzaXRlLCBsYXQsIGN0bWF4X3NkX3AsIHNpemVfc2RfcCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcF9jaGFuZ2UsIGF2Z190ZW1wLCBkYXlzX3Bhc3NlZCksIAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBzZWFzb24sIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYyhjdG1heCwgc2l6ZSkpICU+JSAKICBtdXRhdGUoc2Vhc29uID0gInBlYWtfdG9fbGF0ZSIpICU+JSAgCiAgZHJvcF9uYSgpCgpjYWxjX2hhbGRzID0gZnVuY3Rpb24oeDEsIHgyLCBzZF9wLCBnKXsKICAoKHgyIC8gc2RfcCkgLSAoeDEgLyBzZF9wKSkgLyBnCn0KCmhhbGRhbmVzID0gYmluZF9yb3dzKGVhcmx5X3BlYWssIHBlYWtfbGF0ZSkgJT4lIAogIG11dGF0ZSgiZ2VuX3RpbWUiID0gNTQ5MCooYXZnX3RlbXAgKyAxKV4tMi4wNSwgCiAgICAgICAgICJnZW5zIiA9IGZsb29yKGRheXNfcGFzc2VkIC8gZ2VuX3RpbWUpLAogICAgICAgICAiY3RtYXhfaGFsZGFuZXMiID0gY2FsY19oYWxkcyh4MiA9IGN0bWF4X3R3bywgeDEgPSBjdG1heF9vbmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9wID0gY3RtYXhfc2RfcCwgZyA9IGdlbnMpLAogICAgICAgICAic2l6ZV9oYWxkYW5lcyIgPSBjYWxjX2hhbGRzKHgyID0gc2l6ZV90d28sIHgxID0gc2l6ZV9vbmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3AgPSBzaXplX3NkX3AsIGcgPSBnZW5zKSkKCmhhbGRhbmVzICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChzaXRlLCBzZWFzb24sIGN0bWF4X2hhbGRhbmVzLCBzaXplX2hhbGRhbmVzKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGN0bWF4X2hhbGRhbmVzLCBzaXplX2hhbGRhbmVzKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSBjKCJ0eXBlIiwgTkEpLCAKICAgICAgICAgICAgICAgbmFtZXNfc2VwID0gIl8iLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiaGFsZGFuZXMiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gdHlwZSwgeSA9IGhhbGRhbmVzLCBncm91cCA9IHNpdGUsIGNvbG91ciA9IHNpdGUpKSArIAogIGZhY2V0X3dyYXAoc2Vhc29ufi4pICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKU2hvd24gYmVsb3cgYXJlIHRoZSBoYWxkYW5lIHZhbHVlcyBwbG90dGVkIGFnYWluc3QgbGF0aXR1ZGUuIAoKYGBge3IgaGFsZGFuZXMtbGF0LXBsb3QsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD04fQpjdG1heF9oYWxkYW5lcyA9IGdncGxvdChoYWxkYW5lcywgYWVzKHggPSBsYXQsIHkgPSBjdG1heF9oYWxkYW5lcywgY29sb3VyID0gc2l0ZSwgc2hhcGUgPSBzZWFzb24pKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNpdGVfY29scykgKyAKICBsYWJzKHggPSAiTGF0aXR1ZGUiLAogICAgICAgeSA9ICJDaGFuZ2UgaW4gQ1RtYXggKGhhbGRhbmVzKSIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQoKc2l6ZV9oYWxkYW5lcyA9IGdncGxvdChoYWxkYW5lcywgYWVzKHggPSBsYXQsIHkgPSBzaXplX2hhbGRhbmVzLCBjb2xvdXIgPSBzaXRlLCBzaGFwZSA9IHNlYXNvbikpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc2l0ZV9jb2xzKSArIAogIGxhYnMoeCA9ICJMYXRpdHVkZSIsCiAgICAgICB5ID0gIkNoYW5nZSBpbiBTaXplIChoYWxkYW5lcykiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkKCmdnYXJyYW5nZShjdG1heF9oYWxkYW5lcywgc2l6ZV9oYWxkYW5lcywgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJyaWdodCIsIG5yb3cgPSAyKQpgYGAKCgoKIyMgTmV4dCBTdGVwcwoKQWZ0ZXIgcGhlbm90eXBpbmcsIGVhY2ggaW5kaXZpZHVhbCB3YXMgcHJlc2VydmVkIGluIDk1JSBldGhhbm9sLiBJbmRpdmlkdWFsIEROQSBsaWJyYXJpZXMgd2lsbCBiZSBwcmVwYXJlZCB1c2luZyBUd2lzdCBCaW8gOTYtcGxleCBwcmVwIGtpdHMsIHRoZW4gc2VxdWVuY2VkIG9uIGFuIElsbHVtaW5hIE5vdmFTZXEgWCBQbHVzLiBVc2luZyB0aGUgbG93LWNvdmVyYWdlIHdob2xlIGdlbm9tZSBzZXF1ZW5jZXMsIHdlIHdpbGwgZXhhbWluZSBzZWFzb25hbCBwYXR0ZXJucyBpbiBhbGxlbGUgZnJlcXVlbmN5IGNoYW5nZSwgYW5kIGNvbXBhcmUgdGhlc2UgZmluZSBzY2FsZSB0ZW1wb3JhbCBwYXR0ZXJucyB3aXRoIHRoZSBsYXJnZXIgbGF0aXR1ZGluYWwgcGF0dGVybnMgaW4gYWxsZWxlIGZyZXF1ZW5jeSB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgc2FtZSBhbGxlbGVzIGRyaXZpbmcgcmFwaWQgc2Vhc29uYWwgYWRhcHRhdGlvbiBhcmUgaW4gcGxheSBvdmVyIGxhcmdlciBzcGF0aWFsIChhbmQgbG9uZ2VyIHRlbXBvcmFsKSBzY2FsZXMuCgojIyBNaXNjLiBEZXRhaWxzCgpgYGB7ciB0ZW1wLXJlY29yZC1wbG90LCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQpnZ3Bsb3QodGVtcF9yZWNvcmQsIGFlcyh4ID0gbWludXRlX3Bhc3NlZCwgeSA9IHRlbXBfQywgZ3JvdXAgPSBmYWN0b3IocnVuKSkpICsgCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAwLjMsIGludGVyY2VwdCA9IG1lYW4odGVtcF9yZWNvcmRbdGVtcF9yZWNvcmQkbWludXRlX2ludGVydmFsID09IDAsIDhdKSkgKyAKICBnZW9tX2FibGluZShzbG9wZSA9IDAuMSwgaW50ZXJjZXB0ID0gbWVhbih0ZW1wX3JlY29yZFt0ZW1wX3JlY29yZCRtaW51dGVfaW50ZXJ2YWwgPT0gMCwgOF0pKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjIsIGFscGhhID0gMC44KSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGZ1bGxfZGF0YSwgCiAgICAgICAgICAgICBhZXMoeCA9IHRpbWUsIHkgPSBjdG1heCArIDAuNCksCiAgICAgICAgICAgICBzaXplID0gMiwKICAgICAgICAgICAgIHNoYXBlID0gMjUpICsKICBsYWJzKHggPSAiVGltZSBwYXNzZWQgKG1pbnV0ZXMpIiwKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKGRlZ3JlZXMgQykiLAogICAgICAgZmlsbCA9ICJUcmlhbCBOdW1iZXIiKSArIAogIGd1aWRlcyhjb2xvdXIgPSAibm9uZSIpICsgCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCmBgYHtyIHJhbXAtcmVjb3JkLXBsb3QsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTZ9CnJhbXBfcmVjb3JkMiA9IHJhbXBfcmVjb3JkICU+JSAKICBncm91cF9ieShydW4sIG1pbnV0ZV9pbnRlcnZhbCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3JhbXAgPSBtZWFuKHJhbXBfcGVyX21pbnV0ZSkpICU+JSAKICB1bmdyb3VwKCkKCmdncGxvdChyYW1wX3JlY29yZDIsIGFlcyh4ID0gbWludXRlX2ludGVydmFsLCB5ID0gbWVhbl9yYW1wKSkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjMpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4xKSArIAogICNnZW9tX3BvaW50KCkgKyAKICBnZW9tX2hleChiaW5zID0gMzApICsgCiAgeWxpbSgwLCAwLjM1KSArIAogIGxhYnMoeSA9ICJSYW1wIFJhdGUgKGRlZy4gQyAvIG1pbi4pIiwKICAgICAgIHggPSAiVGltZSBpbnRvIHJ1biAobWludXRlKSIpICsgCiAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSAxNikgCmBgYAo=